﻿#include "core/scene.h"
#include "klbmem/klb_mem.h"
#include "klbutil/klb_hlist.h"


typedef struct scene_t_
{
    klb_hlist_t*        p_hlist;        ///< game engine object 查找表
}scene_t;


//////////////////////////////////////////////////////////////////////////



//////////////////////////////////////////////////////////////////////////

static void scene_push_child(geobj_t* p_parent, geobj_t* p_sub)
{
    assert(NULL != p_parent);

    // 父
    p_sub->p_parent = p_parent;

    if (NULL == p_parent->p_child)
    {
        p_parent->p_child = p_sub;
    }
    else
    {
        geobj_t* p_next = p_parent->p_child;
        while (NULL != p_next->p_next)
        {
            p_next = p_next->p_next;
        }

        assert(NULL != p_next);

        p_next->p_next = p_sub;
        p_sub->p_prev = p_next;
    }
}

static void scene_split_path_name(const char* p_path_name, char** p_dir, int* p_dir_len)
{
    const char* p = p_path_name ? strrchr(p_path_name, '/') : NULL;

    if (NULL != p)
    {
        *p_dir = (char*)p_path_name;
        *p_dir_len = p - p_path_name;
    }
    else
    {
        *p_dir = NULL;
        *p_dir_len = 0;
    }
}


/// @brief 插入
int scene_append(geobj_t* p_obj, const char* p_path, geobj_t* p_data)
{
    scene_t* p_scene = (scene_t*)p_obj->extra;

    char* p_dir = NULL;
    int dir_len = 0;
    scene_split_path_name(p_path, &p_dir, &dir_len);

    if (0 < dir_len)
    {
        geobj_t* p_parent = (geobj_t*)klb_hlist_find(p_scene->p_hlist, p_dir, dir_len);
        if (NULL == p_parent)
        {
            return 1;
        }

        scene_push_child(p_parent, p_data);
        klb_hlist_push_tail(p_scene->p_hlist, p_path, strlen(p_path), p_data);
    }
    else
    {
        if (NULL != klb_hlist_find_iter(p_scene->p_hlist, p_path, strlen(p_path)))
        {
            return 2; // 已存在
        }

        // 首位
        scene_push_child(p_obj, p_data);
        klb_hlist_push_tail(p_scene->p_hlist, p_path, strlen(p_path), p_data);
    }

    return 0;
}

/// @brief 移除
int scene_remove(geobj_t* p_obj, const char* p_path)
{
    scene_t* p_scene = (scene_t*)p_obj->extra;

    return 1;
}

//////////////////////////////////////////////////////////////////////////

/// @brief 销毁
void scene_destroy(geobj_t* p_obj)
{
    scene_t* p_scene = (scene_t*)p_obj->extra;

    klb_hlist_clear(p_scene->p_hlist, NULL, NULL);

    KLB_FREE_BY(p_scene->p_hlist, klb_hlist_destroy);
    KLB_FREE(p_obj);
}

/// @brief 向object设置数据
int on_scene_set(geobj_t* p_obj, const klb_map_t* p_map)
{
    scene_t* p_scene = (scene_t*)p_obj->extra;

    return 0;
}

/// @brief 向object获取数据
klb_map_t* on_scene_get(geobj_t* p_obj, const klb_map_t* p_map)
{
    scene_t* p_scene = (scene_t*)p_obj->extra;

    return NULL;
}

//////////////////////////////////////////////////////////////////////////

geobj_t* scene_create()
{
    geobj_t* p_obj = KLB_MALLOCZ(geobj_t, 1, sizeof(scene_t));
    scene_t* p_scene = (scene_t*)p_obj->extra;

    p_obj->vtable.cb_destroy = scene_destroy;
    p_obj->vtable.cb_set = on_scene_set;
    p_obj->vtable.cb_get = on_scene_get;

    // init
    p_scene->p_hlist = klb_hlist_create(0);

    return p_obj;
}
